home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 10
/
AACD 10.iso
/
AACD
/
Utilities
/
GOCR
/
src
/
pnm.cc
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-29
|
7KB
|
216 lines
#include <stdio.h>
// #include <stdlib.h>
// #include <assert.h>
#include "pnm.h"
#define EE() fprintf(stderr,"\nERROR "__FILE__" L%d: ",__LINE__)
#define E0(x0) {EE();fprintf(stderr,x0 "\n"); }
#define F0(x0) {EE();fprintf(stderr,x0 "\n"); exit(1);}
#define F1(x0,x1) {EE();fprintf(stderr,x0 "\n",x1); exit(1);}
#define F2(x0,x1,x2) {EE();fprintf(stderr,x0 "\n",x1,x2);exit(1);}
// --- needed for reading PNM-files
int spc(char c){ return ((c==' ' || c=='\t'
|| c=='\r' || c=='\n') ? 1 : 0 ); }
int num(char c){ return ((c>='0' && c<='9' ) ? 1 : 0 ); }
char read_char(FILE *f1){ // filter #-comments
char c; int m;
for(m=0;;){
c=fgetc(f1);
if( feof(f1) ) E0("read feof");
if( ferror(f1) ) F0("read ferror");
if( c=='#' ) { m=1; continue; }
if( m==0 ) return c;
if( c=='\n' ) m=0;
}
}
void readpgm(char *name,pix *p,int vvv){ // raw-ppm
char c1,c2; int nx,ny,nc,mod,i,j,k; // buffer
FILE *f1; unsigned char *pic;
if(name[0]=='-' && name[1]==0){
f1=stdin; /* is this correct ??? */
} else {
f1=fopen(name,"rb"); if(!f1)F1("opening file %s",name);
}
c1=fgetc(f1); if(feof(f1))F0("read");
c2=fgetc(f1); if(feof(f1))F0("read");
if(c1!='P')F0("first byte should be P in PNM-files");
if(c2!='5' && c2!='4' && c2!='6')// F0("no PNM-RAW"); // PGM-RAW,PBM-RAW,PPM-RAW
if(c2!='1' && c2!='2' && c2!='3')F0("no PNM");
nx=ny=nc=0; if( c2=='4' || c2=='1') nc=1;
for(mod=0;((c2=='5' || c2=='2') && (mod&7)<6)
|| ((c2=='6' || c2=='3') && (mod&7)<6)
|| ((c2=='4' || c2=='1') && (mod&7)<4);)
{ // mode: 0,2,4=[ |\t|\r|\n]
// 1=nx 3=ny 5=nc 8-13=#rem
c1=read_char(f1); // frueher: # mod|=8
if( (mod & 1)==0 ) // whitespaces
if( !spc(c1) ) mod++;
if( (mod & 1)==1 )
if( !num(c1) ) {
if( !spc(c1) )F0("unexpected character");
mod++; }
else if(mod==1) nx=nx*10+c1-'0';
else if(mod==3) ny=ny*10+c1-'0';
else if(mod==5) nc=nc*10+c1-'0';
}
if(nc>=256)F0("nc >= 256"); // realy RAW?
if(vvv)
printf("# PNM P%c x=%d y=%d c=%d head=%ld",c2,nx,ny,nc,ftell(f1));
if( c2=='4' && (nx&7)!=0 ){
/* nx=(nx+7)&~7;*/ if(vvv)printf(" PBM2PGM nx %d",(nx+7)&~7);
}
fflush(stdout);
// pic=new Uchar[ (*nx)*(*ny) ]; // errors!
pic=new unsigned char[ nx*ny*((c2=='6')?3:1) ];
if(pic==NULL)F0("memory failed"); // no memory
if( c2=='5' )
if(ny!=(int)fread(pic, nx,ny,f1))F0("read"); // read all lines
if( c2=='2' )for(mod=j=i=0;i<nx*ny && !feof(f1);){ // not very clever
c1=read_char(f1);
if( !num(c1) ) { if( !spc(c1) )F0("unexpected char");
if(1&mod) { pic[i]=j*255/nc; i++; j=0; mod=0; } }
else { j=j*10+c1-'0'; mod=1; };
}
if( c2=='1' )for(mod=j=i=0,nc=255;i<nx*ny && !feof(f1);){ // PBM-ASCII 0001100
c1=read_char(f1);
if( num(c1) ) { pic[i]=((c1=='0')?255:0); i++; }
else if( !spc(c1) )F0("unexpected char");
}
if( c2=='3' )for(mod=k=j=i=0;i<nx*ny*3 && !feof(f1);){
c1=read_char(f1);
if( !num(c1) ) { if( !spc(c1) )F0("unexpected char");
if(1&mod) { k+=j; if(mod==5){ pic[i]=k/3; i++; }
j=0; mod=(mod+1)%6; } }
else { j=j*10+c1-'0'; if(!(mod&1)) mod++; };
}
if( c2=='6' ){
if(ny!=(int)fread(pic, 3*nx,ny,f1))F0("read"); // read all lines
int lx,ly;
for(ly=0;ly<ny;ly++)
for(lx=0;lx<nx;lx++)
pic[lx+ly*nx]=( pic[0+3*lx+3*ly*nx]
+pic[1+3*lx+3*ly*nx]
+pic[2+3*lx+3*ly*nx] ) / 3;
}
if( c2=='4' ){ // PBM-RAW
int dx=(nx+7)&~7; // dx (mod 8)
if(ny!=(int)fread(pic,dx>>3,ny,f1))F0("read"); // read all bytes
int lx,ly;
for(ly=ny-1;ly>=0;ly--)
for(lx=nx-1;lx>=0;lx--)
pic[lx+ly*nx]=( (128 & pic[(lx+ly*dx)>>3]<<(lx & 7)) ? 0 : 255 );
#if 0
// using gray values for fuzzy logic
for(ly=ny-2;ly>0;ly--)
for(lx=nx-2;lx>0;lx--){ // takes time!
pic[lx+ly*nx]=
((pic[ lx + ly *nx]>128)?192:64) // reduce contrast
+((pic[(lx+1)+(ly )*nx]>128)? 8:-8) // max 4*8+4*4=48;
+((pic[(lx-1)+(ly )*nx]>128)? 8:-8)
+((pic[(lx )+(ly+1)*nx]>128)? 8:-8)
+((pic[(lx )+(ly-1)*nx]>128)? 8:-8)
+((pic[(lx+1)+(ly+1)*nx]>128)? 4:-4)
+((pic[(lx-1)+(ly+1)*nx]>128)? 4:-4)
+((pic[(lx+1)+(ly-1)*nx]>128)? 4:-4)
+((pic[(lx-1)+(ly-1)*nx]>128)? 4:-4);
}
#endif
nc=255;
}
if(name[0]=='-' && name[1]==0){
f1=NULL;
} else {
fclose(f1);
}
p->p=pic; p->x=nx; p->y=ny; p->bpp=1;
if(vvv)printf("\n");
}
int writepgm(char *nam,pix p){// P5 raw-pgm
FILE *f1;int a,x,y;
f1=fopen(nam,"wb");if(!f1)F0("open"); // open-error
fprintf(f1,"P5\n%d %d\n255\n",p.x,p.y);
if(p.bpp==3)
for(y=0;y<p.y;y++)
for(x=0;x<p.x;x++){ // set bit
a=x+y*p.x;
p.p[a]=(p.p[3*a+0]+p.p[3*a+1]+p.p[3*a+2])/3;
}
if(p.y!=(int)fwrite(p.p,p.x,p.y,f1))F0("write"); // write all lines
fclose(f1);
return 0;
}
// pgm2ppm, use last 3 bits for farbcoding
int writeppm(char *nam,pix p){// P6 raw-ppm
FILE *f1;int x,y; unsigned char rgb[3];
f1=fopen(nam,"wb");if(!f1)F0("open"); // open-error
fprintf(f1,"P6\n%d %d\n255\n",p.x,p.y);
if( p.bpp==1 )
for(y=0;y<p.y;y++)
for(x=0;x<p.x;x++){
rgb[0]=rgb[1]=rgb[2]=p.p[x+y*p.x];
if(p.p[x+y*p.x]&4) rgb[0]=64;
if(p.p[x+y*p.x]&2) rgb[1]=64;
if(p.p[x+y*p.x]&1) rgb[2]=64;
if( 1!=(int)fwrite(rgb,3,1,f1) )F0("write");
}
if( p.bpp==3 )
if( p.y!=(int)fwrite(p.p,3*p.x,p.y,f1) )F0("write");
fclose(f1);
return 0;
}
// high bit = first,
int writepbm(char *nam,pix p){// P4 raw-pbm
FILE *f1;int x,y,a,b,dx,i;
dx=(p.x+7)&~7; // enlarge to a factor of 8
for(y=0;y<p.y;y++)
for(x=0;x<p.x;x++){ // set bit
a=(x+y*dx)>>3;b=7-(x&7); // adress an bitnumber
i=x+y*p.x;
if(p.bpp==3) i=(p.p[3*i+0]+p.p[3*i+1]+p.p[3*i+2])/3;
else i= p.p[ i ];
i=((i>127)?0:1);
p.p[a]=(p.p[a] & (~1<<b)) | i<<b;
}
f1=fopen(nam,"wb");if(!f1)F0("open"); // open-error
fprintf(f1,"P4\n%d %d\n",p.x,p.y);
if(p.y!=(int)fwrite(p.p,dx>>3,p.y,f1))F0("write"); // write all lines
fclose(f1);
return 0;
}
// ------------------------------------------------------------------------
// ----- count colors ------ create histogram -------
void makehisto(pix p, unsigned col[256], int vvv){
int i,j,x,y;
for(i=0;i<256;i++) col[i]=0;
for(x=0;x<p.x;x++)
for(y=0;y<p.y;y++) col[ p.p[x+p.x*y] ]++;
for(i=255;i> 0;i--) if( col[i] ) break; // brightest pixel
for(j= 0;j<255;j++) if( col[j] ) break; // darkest
if(i <64) printf("Warning: max intensity=%d<64, too dark\n",i);
if(i-j<64) printf("Warning: contrast=(%d-%d)<64\n",i,j);
if(i-j<=8)F0("to less contrast ???");
/* smoothen */
for(j=8;j>0;j--)for(i=0;i<255-j;i++){
x=col[i];y=col[i+1];col[i]=(3*x+y)/4;col[i+1]=(x+3*y)/4;
}
/* how to detect main maximas? */
if(vvv){
printf("#!gnuplot\n"
" set data style lines\n"
" plot \"-\"\n");
for(i=0;i<256;i++)
printf(" %8d %8d\n",i,col[i]);
printf("e\npause -1\n");
}
}